package com.example.rustfs.service;

import com.example.rustfs.config.RustFsConfig;
import com.example.rustfs.dao.RecycleBinDao;
import com.example.rustfs.dto.DeletedFileInfo;
import com.example.rustfs.entity.DeletedFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;

import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 回收站服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RecycleBinService {
    
    private final RecycleBinDao recycleBinDao;
    private final S3Client s3Client;
    private final RustFsConfig rustFsConfig;
    private static final String RECYCLE_BIN_PREFIX = ".recycle/";
    
    /**
     * 移动文件到回收站
     */
    public void moveToRecycleBin(Long userId, String fileKey, String fileName, Long fileSize) {
        try {
            // 生成回收站中的key
            String deletedKey = RECYCLE_BIN_PREFIX + userId + "/" + UUID.randomUUID() + "_" + fileName;
            
            // 复制文件到回收站
            CopyObjectRequest copyRequest = CopyObjectRequest.builder()
                    .sourceBucket(rustFsConfig.getBucketName())
                    .sourceKey(fileKey)
                    .destinationBucket(rustFsConfig.getBucketName())
                    .destinationKey(deletedKey)
                    .build();
            s3Client.copyObject(copyRequest);
            
            // 删除原文件
            DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                    .bucket(rustFsConfig.getBucketName())
                    .key(fileKey)
                    .build();
            s3Client.deleteObject(deleteRequest);
            
            // 保存删除记录
            DeletedFile deletedFile = new DeletedFile();
            deletedFile.setUserId(userId);
            deletedFile.setOriginalKey(fileKey);
            deletedFile.setDeletedKey(deletedKey);
            deletedFile.setFileName(fileName);
            deletedFile.setFileSize(fileSize);
            deletedFile.setFileType(getFileType(fileName));
            deletedFile.setDeletedTime(LocalDateTime.now());
            deletedFile.setExpireTime(LocalDateTime.now().plusDays(30));
            
            recycleBinDao.save(deletedFile);
            
            log.info("文件已移至回收站: {} -> {}", fileKey, deletedKey);
        } catch (Exception e) {
            log.error("移至回收站失败", e);
            throw new RuntimeException("移至回收站失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取用户回收站文件列表
     */
    public List<DeletedFile> getRecycleBinFiles(Long userId) {
        return recycleBinDao.findByUserId(userId);
    }
    
    /**
     * 获取用户回收站文件列表（DTO）
     */
    public List<DeletedFileInfo> getRecycleBinFilesInfo(Long userId) {
        List<DeletedFile> files = recycleBinDao.findByUserId(userId);
        return files.stream().map(this::toDeletedFileInfo).collect(Collectors.toList());
    }
    
    private DeletedFileInfo toDeletedFileInfo(DeletedFile file) {
        DeletedFileInfo info = new DeletedFileInfo();
        info.setId(file.getId());
        info.setFileName(file.getFileName());
        info.setFileSize(formatFileSize(file.getFileSize()));
        info.setDeletedTime(file.getDeletedTime());
        info.setExpireTime(file.getExpireTime());
        info.setDeletedKey(file.getDeletedKey());
        return info;
    }
    
    private String formatFileSize(long size) {
        if (size <= 0) return "0 B";
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }
    
    /**
     * 恢复文件
     */
    public void restoreFile(Long userId, Long deletedFileId) {
        DeletedFile deletedFile = recycleBinDao.findById(deletedFileId);
        if (deletedFile == null || !deletedFile.getUserId().equals(userId)) {
            throw new RuntimeException("文件不存在或无权限");
        }
        
        try {
            // 复制回原位置
            CopyObjectRequest copyRequest = CopyObjectRequest.builder()
                    .sourceBucket(rustFsConfig.getBucketName())
                    .sourceKey(deletedFile.getDeletedKey())
                    .destinationBucket(rustFsConfig.getBucketName())
                    .destinationKey(deletedFile.getOriginalKey())
                    .build();
            s3Client.copyObject(copyRequest);
            
            // 删除回收站中的文件
            DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                    .bucket(rustFsConfig.getBucketName())
                    .key(deletedFile.getDeletedKey())
                    .build();
            s3Client.deleteObject(deleteRequest);
            
            // 删除记录
            recycleBinDao.delete(deletedFileId);
            
            log.info("文件已恢复: {} -> {}", deletedFile.getDeletedKey(), deletedFile.getOriginalKey());
        } catch (Exception e) {
            log.error("文件恢复失败", e);
            throw new RuntimeException("文件恢复失败: " + e.getMessage());
        }
    }
    
    /**
     * 永久删除文件
     */
    public void deletePermanently(Long userId, Long deletedFileId) {
        DeletedFile deletedFile = recycleBinDao.findById(deletedFileId);
        if (deletedFile == null || !deletedFile.getUserId().equals(userId)) {
            throw new RuntimeException("文件不存在或无权限");
        }
        
        try {
            // 删除S3中的文件
            DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                    .bucket(rustFsConfig.getBucketName())
                    .key(deletedFile.getDeletedKey())
                    .build();
            s3Client.deleteObject(deleteRequest);
            
            // 删除记录
            recycleBinDao.delete(deletedFileId);
            
            log.info("文件已永久删除: {}", deletedFile.getDeletedKey());
        } catch (Exception e) {
            log.error("永久删除失败", e);
            throw new RuntimeException("永久删除失败: " + e.getMessage());
        }
    }
    
    /**
     * 清空回收站
     */
    public void emptyRecycleBin(Long userId) {
        List<DeletedFile> files = recycleBinDao.findByUserId(userId);
        for (DeletedFile file : files) {
            try {
                DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
                        .bucket(rustFsConfig.getBucketName())
                        .key(file.getDeletedKey())
                        .build();
                s3Client.deleteObject(deleteRequest);
                recycleBinDao.delete(file.getId());
            } catch (Exception e) {
                log.error("删除文件失败: {}", file.getDeletedKey(), e);
            }
        }
        log.info("用户 {} 的回收站已清空", userId);
    }
    
    private String getFileType(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "unknown";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
    }
}

